// Copyright [2022] <Shizhen Zhao>

#ifndef SRLH_PULSE_H_
#define SRLH_PULSE_H_

#include <functional>
#include <queue>
#include <utility>
#include <vector>
#include <ctime>

#include "algorithm.h"
#include "graph.h"

const int kMaxDelay = 1000;

class SrlgPulse : public Algorithm
{
public:
    SrlgPulse() : accurate_(true) {}
    ~SrlgPulse();
    void SetupTopology(Graph *graph) override;
    PathPair FindPathPair(const Flow &flow) override;
    Path FindPath(const Flow &flow) override;
    void print() const;

private:
    template <class T>
    struct Node
    {
        Node(T id_in, int distance_in)
            : id(id_in), distance(distance_in) {}

        friend bool operator<(const Node<T> &a, const Node<T> &b)
        {
            return a.distance > b.distance;
        }
        T id;
        int distance;
    };

    struct PulseInfo
    {
        PulseInfo() : src_delay_to_cost_map(kMaxDelay, kMaxValue) {}
        void Clear()
        {
            for (int i = 0; i < kMaxDelay; ++i)
            {
                src_delay_to_cost_map[i] = kMaxValue;
            }
        }
        std::vector<double> src_delay_to_cost_map;
    };

    // Helper functions
    void DstDijkstra(NodeId dst_node, bool flag, double *node_to_dst_dis);
    void Dfs();
    void APDfs(int type);
    Path BPDfs(const Path &ap_path);
    // Path BPDfs();

    bool updateSrcPath(NodeId u, double cost, double delay);
    void SortLinks();

    //  functions for delay diff
    void RemoveUsedNodes(const Path &path);
    void RemoveUsedLinks(const Path &path);
    void RetrieveUsedLinks(const Path &path);
    void RemoveUsedSrlgs(const Path &path);
    void RetrieveUsedSrlgs(const Path &path);
    int find_link_in_conflict_path(Link *link);
    Link* check_conflict(const Path &ap_path, Path &bp_path);
    // void change_ap_link_seq(const Path &ap_path);

    Path NodeSep(const Path &path);
    Path LinkSep(const Path &path);
    Path SrlgSep(const Path &path);

    // Variables for initialization
    double *dst_cost_map_;
    double *dst_delay_map_;
    int num_nodes_;

    // Variables for pulse search
    clock_t start_time_;
    clock_t end_time_;
    bool *src_visited_;

    PulseInfo *info_;
    Flow flow_;
    double total_cost_;
    Path results_;
    std::vector<std::pair<double, double>> time_ms_cost_pairs_;
    bool accurate_;

    // variables for srlg
    PathPair path_pair_;
    bool *bp_visited_;
    Path conflict_set_;
};

#endif // SRLH_PULSE_H_